﻿/* Copyright (c) 2001-2009, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using EffiProz.Core.Errors;

namespace EffiProz.Core.DataTypes
{
    public class Types
    {


        /*
         SQL specifies predefined data types named by the following <key word>s:
         CHARACTER, CHARACTER VARYING, CHARACTER LARGE OBJECT, BINARY LARGE OBJECT,
         NUMERIC, DECIMAL, SMALLINT, INTEGER, BIGINT, FLOAT, REAL, DOUBLE PRECISION,
         BOOLEAN, DATE, TIME, TIMESTAMP, and INTERVAL. Also BINARY and VARBINARY
         in SQL post-2003
         SQL 2003 adds DATALINK in Part 9: Management of External Data (SQL/MED)
         and adds XML in Part 14: XML-Related Specifications (SQL/XML)
         */

        // CLI type list from Table 37
        public const int SQL_CHAR = 1;
        public const int SQL_NUMERIC = 2;
        public const int SQL_DECIMAL = 3;
        public const int SQL_INTEGER = 4;
        public const int SQL_SMALLINT = 5;
        public const int SQL_FLOAT = 6;
        public const int SQL_REAL = 7;
        public const int SQL_DOUBLE = 8;
        public const int SQL_VARCHAR = 12;
        public const int SQL_BOOLEAN = 16;
        public const int SQL_USER_DEFINED_TYPE = 17;
        public const int SQL_ROW = 19;
        public const int SQL_REF = 20;
        public const int SQL_BIGINT = 25;             // different in JDBC
        public const int SQL_BLOB = 30;             // different in JDBC
        public const int SQL_CLOB = 40;             // different in JDBC
        public const int SQL_ARRAY = 50;             // different in JDBC - not predefined
        public const int SQL_MULTISET = 55;                      //
        public const int SQL_BINARY = 60;                      // different in JDBC -in SQL post-2003
        public const int SQL_VARBINARY = 61;                     // different in JDBC - in SQL post-2003
        public const int SQL_DATE = 91;
        public const int SQL_TIME = 92;
        public const int SQL_TIMESTAMP = 93;     //
        public const int SQL_TIME_WITH_TIME_ZONE = 94;
        public const int SQL_TIMESTAMP_WITH_TIME_ZONE = 95;     //
        public const int SQL_INTERVAL_YEAR = 101;    //
        public const int SQL_INTERVAL_MONTH = 102;
        public const int SQL_INTERVAL_DAY = 103;
        public const int SQL_INTERVAL_HOUR = 104;
        public const int SQL_INTERVAL_MINUTE = 105;
        public const int SQL_INTERVAL_SECOND = 106;
        public const int SQL_INTERVAL_YEAR_TO_MONTH = 107;
        public const int SQL_INTERVAL_DAY_TO_HOUR = 108;
        public const int SQL_INTERVAL_DAY_TO_MINUTE = 109;
        public const int SQL_INTERVAL_DAY_TO_SECOND = 110;
        public const int SQL_INTERVAL_HOUR_TO_MINUTE = 111;
        public const int SQL_INTERVAL_HOUR_TO_SECOND = 112;
        public const int SQL_INTERVAL_MINUTE_TO_SECOND = 113;

        // used where local defines are used in the same range as SQL type numbers
        public const int SQL_TYPE_NUMBER_LIMIT = 256;

        // These values are not in table 37 of the SQL CLI 2003 FCD, but some
        // are found in tables 6-9 and some are found in Annex A1:
        // c Header File SQLCLI.H and/or addendums in other documents,
        // such as:
        // SQL 2003 Part 9: Management of External Data (SQL/MED) : DATALINK
        // SQL 2003 Part 14: XML-Related Specifications (SQL/XML) : XML
        public const int SQL_BIT = 14;                   // is in SQL99 but removed from 2003
        public const int SQL_BIT_VARYING = 15;                   // is in SQL99 but removed from 2003
        public const int SQL_DATALINK = 70;
        public const int SQL_UDT = 17;
        public const int SQL_UDT_LOCATOR = 18;
        public const int SQL_BLOB_LOCATOR = 31;
        public const int SQL_CLOB_LOCATOR = 41;
        public const int SQL_ARRAY_LOCATOR = 51;
        public const int SQL_MULTISET_LOCATOR = 56;
        public const int SQL_ALL_TYPES = 0;
        public const int SQL_DATETIME = 9;               // collective name
        public const int SQL_INTERVAL = 10;              // collective name
        public const int SQL_XML = 137;

        // These values are taken from various SQL CLI header files
        public const int SQL_NCHAR = (-8);
        public const int SQL_WCHAR = (-8);
        public const int SQL_WVARCHAR = (-9);
        public const int SQL_NVARCHAR = (-9);
        public const int SQL_WLONGVARCHAR = (-10);
        public const int SQL_NTEXT = (-10);
        public const int SQL_LONGVARBINARY = (-4);
        public const int SQL_IMAGE = (-4);
        public const int SQL_GUID = (-11);
        public const int SQL_VARIANT = (-150);

        // SQL_UDT subcodes
        public const int SQL_SUB_DISTINCT = 1;
        public const int SQL_SUB_STRUCTURED = 2;

        // non-standard type not in JDBC or SQL CLI
        public const int VARCHAR_IGNORECASE = 100;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type
         * <code>ARRAY</code>.
         *
         * @since JDK 1.2
         */
        public const int ARRAY = 2003;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>BIGINT</code>.
         */
        public const int BIGINT = -5;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>BINARY</code>.
         */
        public const int BINARY = -2;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>BIT</code>.
         */
        public const int BIT = -7;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type
         * <code>BLOB</code>.
         *
         * @since JDK 1.2
         */
        public const int BLOB = 2004;

        /**
         * The constant in the Java programming language, somtimes referred to
         * as a type code, that identifies the generic SQL type
         * <code>BOOLEAN</code>.
         *
         * @since JDK 1.4
         */
        public const int BOOLEAN = SQL_BOOLEAN;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>CHAR</code>.
         */
        public const int CHAR = SQL_CHAR;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type
         * <code>CLOB</code>
         *
         * @since JDK 1.2
         */
        public const int CLOB = 2005;

        /**
         * The constant in the Java programming language, somtimes referred to
         * as a type code, that identifies the generic SQL type <code>DATALINK</code>.
         *
         * @since JDK 1.4
         */
        public const int DATALINK = 70;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>DATE</code>.
         */
        public const int DATE = SQL_DATE;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>DECIMAL</code>.
         */
        public const int DECIMAL = SQL_DECIMAL;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type
         * <code>DISTINCT</code>.
         *
         * @since JDK 1.2
         */
        public const int DISTINCT = 2001;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>DOUBLE</code>.
         */
        public const int DOUBLE = SQL_DOUBLE;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>FLOAT</code>.
         */
        public const int FLOAT = SQL_FLOAT;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>INTEGER</code>.
         */
        public const int INTEGER = SQL_INTEGER;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type
         * <code>JAVA_OBJECT</code>.
         *
         * @since JDK 1.2
         */
        public const int CSHARP_OBJECT = 2000;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>LONGVARBINARY</code>.
         */
        public const int LONGVARBINARY = -4;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>LONGVARCHAR</code>.
         */
        public const int LONGVARCHAR = -1;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>NULL</code>.
         */
        public const int NULL = 0;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>NUMERIC</code>.
         */
        public const int NUMERIC = SQL_NUMERIC;

        /**
         * The constant in the Java programming language that indicates
         * that the SQL type is database-specific and
         * gets mapped to a Java object that can be accessed via
         * the methods <code>getObject</code> and <code>setObject</code>.
         */
        public const int OTHER = 1111;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>REAL</code>.
         */
        public const int REAL = SQL_REAL;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type
         * <code>REF</code>.
         *
         * @since JDK 1.2
         */
        public const int REF = 2006;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>SMALLINT</code>.
         */
        public const int SMALLINT = SQL_SMALLINT;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type
         * <code>STRUCT</code>.
         *
         * @since JDK 1.2
         */
        public const int STRUCT = 2002;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>TIME</code>.
         */
        public const int TIME = SQL_TIME;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>TIMESTAMP</code>.
         */
        public const int TIMESTAMP = SQL_TIMESTAMP;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>TINYINT</code>.
         */
        public const int TINYINT = -6;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>VARBINARY</code>.
         */
        public const int VARBINARY = -3;

        /**
         * <P>The constant in the Java programming language, sometimes referred
         * to as a type code, that identifies the generic SQL type
         * <code>VARCHAR</code>.
         */
        public const int VARCHAR = SQL_VARCHAR;

        //    /**
        //     * <P>The constant in the Java programming language, sometimes referred
        //     * to as a type code, that identifies the recent SQL 2003 SQL type
        //     * <code>XML</code>.
        //     *
        //     * @since SQL 2003
        //     * @deprectated
        //     * @see #SQLXML
        //     */
        //    public const int XML = 137;
        //------------------------- JDBC 4.0 -----------------------------------

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type <code>ROWID</code>
         *
         * @since JDK 1.6, HSQLDB 1.8.x
         *
         */
        public const int ROWID = 2008;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type <code>NCHAR</code>
         *
         * @since JDK 1.6, HSQLDB 1.8.x
         */
        public const int NCHAR = -8;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type <code>NVARCHAR</code>.
         *
         * @since JDK 1.6, HSQLDB 1.8.x
         */
        public const int NVARCHAR = -9;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type <code>LONGNVARCHAR</code>.
         *
         * @since JDK 1.6, HSQLDB 1.8.x
         */
        public const int LONGNVARCHAR = -10;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type <code>NCLOB</code>.
         *
         * @since JDK 1.6, HSQLDB 1.8.x
         */
        public const int NCLOB = 2007;

        /**
         * The constant in the Java programming language, sometimes referred to
         * as a type code, that identifies the generic SQL type <code>XML</code>.
         *
         * @since JDK 1.6, HSQLDB 1.8.x
         */
        public const int SQLXML = 2009;

        //----------------------------- End JDBC 4.0 -------------------------------

        /**
         * The default HSQLODB type sub-identifier. This indicates that an
         * HSQLDB type with this sub-type, if supported, is the very closest
         * thing HSQLDB offerers to the JDBC/SQL2003 type
         */
        public const int TYPE_SUB_DEFAULT = 1;

        /**
         * The IGNORECASE type sub-identifier. This indicates that an HSQLDB type
         * with this sub-type, if supported,  is the closest thing HSQLDB offerers
         * to the JDBC/SQL2003 type, except that case is ignored in comparisons
         */
        public const int TYPE_SUB_IGNORECASE = TYPE_SUB_DEFAULT << 2;

        /**
         * Every (type,type-sub) combination known in the HSQLDB context.
         * Not every combination need be supported as a table or procedure
         * column type -- such determinations are handled in DITypeInfo.
         */
        public  int[][] ALL_TYPES = new int[][]{
        new int[]{
            SQL_ARRAY, TYPE_SUB_DEFAULT
        }, new int[]{
            SQL_BIGINT, TYPE_SUB_DEFAULT
        }, new int[]{
            SQL_BINARY, TYPE_SUB_DEFAULT
        }, new int[]{
            SQL_VARBINARY, TYPE_SUB_DEFAULT
        }, new int[]{
            SQL_BLOB, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_BOOLEAN, TYPE_SUB_DEFAULT
        }, new int[]{
            SQL_CHAR, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_CLOB, TYPE_SUB_DEFAULT
        }, new int[]{
            DATALINK, TYPE_SUB_DEFAULT
        }, new int[]{
            SQL_DATE, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_DECIMAL, TYPE_SUB_DEFAULT
        },new int[] {
            DISTINCT, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_DOUBLE, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_FLOAT, TYPE_SUB_DEFAULT
        }, new int[]{
            SQL_INTEGER, TYPE_SUB_DEFAULT
        },new int[] {
            CSHARP_OBJECT, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_NCHAR, TYPE_SUB_DEFAULT
        },new int[] {
            NCLOB, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_ALL_TYPES, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_NUMERIC, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_NVARCHAR, TYPE_SUB_DEFAULT
        },new int[] {
            OTHER, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_REAL, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_REF, TYPE_SUB_DEFAULT
        },new int[] {
            ROWID, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_SMALLINT, TYPE_SUB_DEFAULT
        },new int[] {
            STRUCT, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_TIME, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_TIMESTAMP, TYPE_SUB_DEFAULT
        },new int[] {
            TINYINT, TYPE_SUB_DEFAULT
        },new int[]{
            SQL_VARCHAR, TYPE_SUB_DEFAULT
        },new int[] {
            SQL_VARCHAR, TYPE_SUB_IGNORECASE
        },new int[] {
            SQL_XML, TYPE_SUB_DEFAULT
        }
    };

        // lookup for types
        static Dictionary<string, int> dotNetTypeNumbers;

        static Types()
        {
            dotNetTypeNumbers = new Dictionary<string, int>(32);

            dotNetTypeNumbers.Add("int", Types.SQL_INTEGER);
            dotNetTypeNumbers.Add("System.Int32", Types.SQL_INTEGER);
            dotNetTypeNumbers.Add("double", Types.SQL_DOUBLE);
            dotNetTypeNumbers.Add("System.Double", Types.SQL_DOUBLE);
            dotNetTypeNumbers.Add("System.String", Types.SQL_VARCHAR);
            dotNetTypeNumbers.Add("Datetime", Types.SQL_DATE);
            dotNetTypeNumbers.Add("System.DateTime", Types.SQL_DATE);
            dotNetTypeNumbers.Add("decimal", Types.SQL_DECIMAL);
            dotNetTypeNumbers.Add("System.Decimal", Types.SQL_DECIMAL);
            dotNetTypeNumbers.Add("bool", Types.SQL_BOOLEAN);
            dotNetTypeNumbers.Add("System.Boolean", Types.SQL_BOOLEAN);
            dotNetTypeNumbers.Add("byte", Types.TINYINT);
            dotNetTypeNumbers.Add("System.Byte", Types.TINYINT);
            dotNetTypeNumbers.Add("short", Types.SQL_SMALLINT);
            dotNetTypeNumbers.Add("System.Int16", Types.SQL_SMALLINT);
            dotNetTypeNumbers.Add("long", Types.SQL_BIGINT);
            dotNetTypeNumbers.Add("System.Int64", Types.SQL_BIGINT);
            dotNetTypeNumbers.Add("byte[]", Types.SQL_BINARY);
            dotNetTypeNumbers.Add("System.Object", Types.OTHER);
            dotNetTypeNumbers.Add("System.Void", Types.SQL_ALL_TYPES);

            //
        }

        /**
         * Retieves the type number corresponding to the class
         * of an IN, IN OUT or OUT parameter.  <p>
         *
         * This method extends getTypeNr to return OTHER for
         * primitive arrays, classes that directly implement
         * java.io.Serializable and non-primitive arrays whose
         * base component implements java.io.Serializable,
         * allowing, for instance, arguments and return types of
         * primitive arrays, Serializable objects and arrays,
         * of Serializable objects.  Direct primitive types
         * other than those mapping directly to the internal
         * wrapper form are not yet handled.  That is, HSQLDB
         * cannot yet properly deal with CALLs involving methods
         * with primitive byte, short, float or their
         * corresponding wrappers, due to the way internal
         * conversion works and lack of detection and narrowing
         * code in Function to allow this.  In other words,
         * passing in or retrieving any of the mentioned types
         * always causes conversion to a wider public wrapper
         * which is genrally incompatible under reflective
         * invocation, resulting in an IllegalArgumentException.
         *
         * @param  c a Class instance
         * @return java.sql.Types int value
         * @throws  HsqlException
         */
        public static int getParameterSQLTypeNumber(Type c)
        {

            String name;
            int type;

            if (c == null)
            {
                throw Error.runtimeError(ErrorCode.U_S0500, "Types");
            }

            if (c.Equals(typeof(void)))
            {
                return Types.SQL_ALL_TYPES;
            }

            name = c.FullName;

            if (!dotNetTypeNumbers.TryGetValue(name, out type))
            {

                type = int.MinValue;
                // byte[] is already covered as BINARY in typeAliases
                if (c.IsArray)
                {
                    while (c.IsArray)
                    {
                        c = c.GetElementType();
                    }

                    if (c.IsPrimitive || c.IsSerializable)
                    {
                        type = OTHER;
                    }
                }
                else if (c.IsSerializable)
                {
                    type = OTHER;
                }
            }

            if (type == int.MinValue)
            {
                throw Error.error(ErrorCode.X_42561);
            }

            return type;
        }

        public static bool acceptsZeroPrecision(int type)
        {

            switch (type)
            {

                case Types.SQL_TIME:
                case Types.SQL_TIMESTAMP:
                    return true;

                default:
                    return false;
            }
        }

        public static bool requiresPrecision(int type)
        {

            switch (type)
            {

                case Types.SQL_BIT_VARYING:
                case Types.SQL_VARBINARY:
                case Types.SQL_VARCHAR:
                case Types.SQL_NVARCHAR:
                case Types.VARCHAR_IGNORECASE:
                    return true;

                default:
                    return false;
            }
        }

        /**
         * Types that accept precision params in column definition or casts.
         * CHAR, VARCHAR and VARCHAR_IGNORECASE params
         * are ignored when the sql.enforce_strict_types is false.
         *
         */
        public static bool acceptsPrecision(int type)
        {

            switch (type)
            {

                case Types.LONGVARCHAR:
                case Types.LONGVARBINARY:
                case Types.SQL_BINARY:
                case Types.SQL_BIT:
                case Types.SQL_BIT_VARYING:
                case Types.SQL_BLOB:
                case Types.SQL_CHAR:
                case Types.SQL_NCHAR:
                case Types.SQL_CLOB:
                case Types.NCLOB:
                case Types.SQL_VARBINARY:
                case Types.SQL_VARCHAR:
                case Types.SQL_NVARCHAR:
                case Types.VARCHAR_IGNORECASE:
                case Types.SQL_DECIMAL:
                case Types.SQL_NUMERIC:
                case Types.SQL_FLOAT:
                case Types.SQL_TIME:
                case Types.SQL_TIMESTAMP:
                case Types.SQL_INTERVAL_YEAR:
                case Types.SQL_INTERVAL_YEAR_TO_MONTH:
                case Types.SQL_INTERVAL_MONTH:
                case Types.SQL_INTERVAL_DAY:
                case Types.SQL_INTERVAL_DAY_TO_HOUR:
                case Types.SQL_INTERVAL_DAY_TO_MINUTE:
                case Types.SQL_INTERVAL_DAY_TO_SECOND:
                case Types.SQL_INTERVAL_HOUR:
                case Types.SQL_INTERVAL_HOUR_TO_MINUTE:
                case Types.SQL_INTERVAL_HOUR_TO_SECOND:
                case Types.SQL_INTERVAL_MINUTE:
                case Types.SQL_INTERVAL_MINUTE_TO_SECOND:
                case Types.SQL_INTERVAL_SECOND:
                    return true;

                default:
                    return false;
            }
        }

        public static bool acceptsScaleCreateParam(int type)
        {

            switch (type)
            {

                case Types.SQL_INTERVAL_SECOND:
                    return true;

                case Types.SQL_DECIMAL:
                case Types.SQL_NUMERIC:
                    return true;

                default:
                    return false;
            }
        }

    


        public static String getTypeName(int type)
        {

            switch (type)
            {

                case Types.SQL_ARRAY:
                    return "ARRAY";

                case Types.SQL_BIGINT:
                    return "BIGINT";

                case Types.SQL_BINARY:
                    return "BINARY";

                case Types.SQL_BLOB:
                    return "BLOB";

                case Types.SQL_BOOLEAN:
                    return "BOOLEAN";

                case Types.SQL_CHAR:
                    return "CHAR";

                case Types.SQL_NCHAR:
                    return "NCHAR";

                case Types.SQL_CLOB:
                    return "CLOB";

                case Types.NCLOB:
                    return "NCLOB";

                case Types.SQL_DATALINK:
                    return "DATALINK";

                case Types.SQL_DATE:
                    return "DATE";

                case Types.SQL_DECIMAL:
                    return "DECIMAL";

                case Types.DISTINCT:
                    return "DISTINCT";

                case Types.SQL_DOUBLE:
                    return "DOUBLE";

                case Types.SQL_FLOAT:
                    return "FLOAT";

                case Types.SQL_INTEGER:
                    return "INTEGER";

                case Types.CSHARP_OBJECT:
                    return "CSHARP_OBJECT";

                case Types.SQL_ALL_TYPES:
                    return "NULL";

                case Types.SQL_NUMERIC:
                    return "NUMERIC";

                case Types.OTHER:
                    return "OTHER";

                case Types.SQL_REAL:
                    return "REAL";

                case Types.SQL_REF:
                    return "REF";

                case Types.ROWID:
                    return "ROWID";

                case Types.SQL_SMALLINT:
                    return "SMALLINT";

                case Types.STRUCT:
                    return "STRUCT";

                case Types.SQL_TIME:
                    return "TIME";

                case Types.SQL_TIMESTAMP:
                    return "TIMESTAMP";

                case Types.TINYINT:
                    return "TINYINT";

                case Types.SQL_VARBINARY:
                    return "VARBINARY";

                case Types.SQL_VARCHAR:
                    return "VARCHAR";

                case Types.SQL_NVARCHAR:
                    return "NVARCHAR";

                case Types.VARCHAR_IGNORECASE:
                    return "VARCHAR_IGNORECASE";

                case Types.SQL_XML:
                    return "XML";

                default:
                    return null;
            }
        }



        public static int getMaxDisplaySize(int type)
        {

            switch (type)
            {

                case Types.SQL_BLOB:
                case Types.SQL_CLOB:
                    return int.MaxValue;

                case Types.SQL_BINARY:
                case Types.SQL_LONGVARBINARY:
                case Types.OTHER:
                case Types.SQL_VARBINARY:
                case Types.SQL_XML:
                case Types.ROWID:
                    return int.MaxValue;    // max string length

                case Types.SQL_CHAR:
                case Types.SQL_NCHAR:
                case Types.SQL_VARCHAR:
                case Types.SQL_NVARCHAR:
                    return int.MaxValue;    // max string length

                case Types.SQL_BIGINT:          // PowerBuilder barfs, wants 19

                    // ...not our problem, tho,
                    // according to JDBC
                    return 20;                   // precision + "-".length();

                case Types.SQL_BOOLEAN:
                    return 5;                    // Math.max("true".length(),"false".length);

                case Types.SQL_DATALINK:
                    return 20004;                // same as precision

                case Types.SQL_DECIMAL:
                case Types.SQL_NUMERIC:
                    return 646456995;            // precision + "-.".length()

                case Types.SQL_DATE:
                    return 10;                   // same as precision

                case Types.SQL_INTEGER:
                    return 11;                   // precision + "-".length();

                case Types.SQL_FLOAT:
                case Types.SQL_REAL:
                case Types.SQL_DOUBLE:
                    return 23;                   // String.valueOf(-Double.MAX_VALUE).length();

                case Types.SQL_TIME:
                    return 8;                    // same as precision

                case Types.SQL_SMALLINT:
                    return 6;                    // precision + "-".length();

                case Types.SQL_TIMESTAMP:
                    return 29;                   // same as precision

                case Types.TINYINT:
                    return 4;                    // precision + "-".length();

                default:
                    return 0;                    // unknown
            }
        }

        public static bool isSearchable(int type)
        {

            switch (type)
            {

                case Types.SQL_ARRAY:
                case Types.SQL_BLOB:
                case Types.SQL_CLOB:
                case Types.NCLOB:
                case Types.CSHARP_OBJECT:
                case Types.STRUCT:
                case Types.OTHER:
                case Types.ROWID:
                    return false;

                default:
                    return true;
            }
        }

        public static bool? isCaseSensitive(int type)
        {

            switch (type)
            {

                case Types.SQL_ARRAY:
                case Types.SQL_BLOB:
                case Types.SQL_CLOB:
                case Types.NCLOB:
                case Types.DISTINCT:
                case Types.CSHARP_OBJECT:
                case Types.SQL_ALL_TYPES:
                case Types.SQL_REF:
                case Types.STRUCT:
                case Types.ROWID:
                    return null;

                case Types.SQL_CHAR:
                case Types.SQL_NCHAR:
                case Types.SQL_DATALINK:
                case Types.SQL_VARCHAR:
                case Types.SQL_NVARCHAR:
                case Types.OTHER:
                case Types.SQL_XML:
                    return true;

                case Types.VARCHAR_IGNORECASE:
                default:
                    return false;
            }
        }

        public static bool? isUnsignedAttribute(int type)
        {

            switch (type)
            {

                case Types.SQL_BIGINT:
                case Types.SQL_DECIMAL:
                case Types.SQL_DOUBLE:
                case Types.SQL_FLOAT:
                case Types.SQL_INTEGER:
                case Types.SQL_NUMERIC:
                case Types.SQL_REAL:
                case Types.SQL_SMALLINT:
                case Types.TINYINT:
                    return false;

                default:
                    return null;
            }
        }

        public static int getPrecision(int type)
        {

            switch (type)
            {

                case Types.SQL_BLOB:
                case Types.SQL_CLOB:
                    return int.MaxValue;

                case Types.SQL_BINARY:
                case Types.SQL_CHAR:
                case Types.SQL_NCHAR:
                case Types.OTHER:
                case Types.SQL_VARBINARY:
                case Types.SQL_VARCHAR:
                case Types.SQL_NVARCHAR:
                case Types.SQL_XML:
                    return int.MaxValue;

                case Types.SQL_BIGINT:
                    return 19;

                case Types.SQL_BOOLEAN:
                    return 1;

                case Types.DATALINK:

                    // from SQL CLI spec.  TODO:  Interpretation?
                    return 20004;

                case Types.SQL_DECIMAL:
                case Types.SQL_NUMERIC:

                    // Integer.MAX_VALUE bit 2's complement number:
                    // (Integer.MAX_VALUE-1) / ((ln(10)/ln(2)) bits per decimal digit)
                    // See:  java.math.BigInteger
                    // - the other alternative is that we could report the numprecradix as 2 and
                    // report Integer.MAX_VALUE here
                    return 646456993;

                case Types.SQL_DATE:
                case Types.SQL_INTEGER:
                    return 10;

                case Types.SQL_FLOAT:
                    return 53;    // Oops...52 in memory + 1 implicit bit

                case Types.SQL_REAL:
                case Types.SQL_DOUBLE:
                    return 17;

                case Types.SQL_TIME:
                    return 8;

                case Types.SQL_SMALLINT:
                    return 5;

                case Types.SQL_TIMESTAMP:
                    return 29;

                case Types.TINYINT:
                    return 3;

                default:
                    return 0;
            }
        }

        public static String getColStClsName(int type)
        {

            switch (type)
            {

                case Types.SQL_BLOB:
                    return "System.Byte[]";

                case Types.SQL_CLOB:
                    return "System.Char[]";

                case Types.SQL_BIGINT:
                    return "System.Long";

                case Types.SQL_BINARY:
                case Types.SQL_VARBINARY:

                    // but wrapped by org.hsqldb.Binary
                    return "System.Byte[]";

                case Types.OTHER:

                    // but wrapped by org.hsqldb.JavaObject
                    return "System.Object";

                case Types.SQL_BOOLEAN:
                    return "System.Boolean";

                case Types.SQL_CHAR:
                case Types.SQL_NCHAR:
                case Types.SQL_VARCHAR:
                case Types.SQL_NVARCHAR:
                case Types.SQL_XML:    //?
                    return "System.String";

                case Types.SQL_DATALINK:
                    return "System.Uri";

                case Types.SQL_DATE:
                    return "System.DateTime";

                case Types.SQL_DECIMAL:
                case Types.SQL_NUMERIC:
                    return "System.Decimal";

                case Types.SQL_DOUBLE:
                case Types.SQL_FLOAT:
                case Types.SQL_REAL:
                    return "System.Double";

                case Types.SQL_INTEGER:
                case Types.SQL_SMALLINT:
                case Types.TINYINT:
                    return "System.Int32";

                case Types.SQL_TIME:
                    return "System.DateTime";

                case Types.SQL_TIMESTAMP:
                    return "System.DateTime";

                default:
                    return null;
            }
        }
    }
}
